﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using info.lundin.math;
using System.Collections;
using System.Numerics;

namespace spline
{
    class Functions
    {
        /// <summary>
        /// Возвращает значение ф-ии по ее строковому представлению
        /// </summary>
        /// <param name="s">Строковое представление ф-ии</param>
        /// <param name="x">Значение х</param>
        /// <returns></returns>
        /// 

        private const double H = 0.000001;
        public static double f(string s, double x)
        {
            ExpressionParser Parser = new ExpressionParser();
            Hashtable h = new Hashtable();
            h.Add("x", x.ToString());
            return Parser.Parse(s, h);
        }

        public static double derivate(string s, double x) {
            ExpressionParser Parser = new ExpressionParser();
            Hashtable h = new Hashtable();
            h.Add("x", (x + H).ToString());
            double xplusd = Parser.Parse(s, h);
            h.Clear();
            h.Add("x", (x - H).ToString());
            double xminusd = Parser.Parse(s, h);
            return (xplusd - xminusd)/(2*H);
        }

        static public double first_pow(double a, double b) {
            return -b / a;
        }

        static public void second_pow(double a, double b, double c, out double x1, out double x2) {
            double D = Math.Pow(b, 2) - 4 * a * c;
            x1 = x2 = 0;
            if (D < 0) {
                x1 = Double.NaN;
                x2 = Double.NaN;
            }
            else if (D > 0) {
                x1 = (-b + Math.Sqrt(D)) / (2 * a);
                x2 = (-b - Math.Sqrt(D)) / (2 * a);
            }
            else if (D == 0) {
                x1 = x2 = -b / (2 * a);
            }

        }


        public static void third_pow(double a, double b, double c, double d, out double x1, out double x2, out double x3) {
            x1 = x2 = x3 = 0;
            double q = (2 * b * b * b - 9 * a * b * c + 27 * a * a * d) / (27 * a * a * a);
            double p = (3 * a * c - b * b) / (3 * a * a);
            double s = ((4 * (3 * a * c - b * b) * (3 * a * c - b * b) * (3 * a * c - b * b)) + (2 * b * b * b - 9 * a * b * c + 27 * a * a * d) * (2 * b * b * b - 9 * a * b * c + 27 * a * a * d)) / (2916 * a * a * a * a * a * a);
            double f = 0;
            if (s < 0) {
                if (q < 0) {
                    f = Math.Atan(Math.Sqrt(-s) / (-q / 2));
                }
                if (q > 0) {
                    f = Math.Atan(Math.Sqrt(-s) / (-q / 2)) + Math.PI;
                }
                if (q == 0) {
                    f = Math.PI / 2;
                }
                x1 = 2 * Math.Sqrt(-p / 3) * Math.Cos(f / 3) - b / a / 3;
                x2 = 2 * Math.Sqrt(-p / 3) * Math.Cos(f / 3 + 2 * Math.PI / 3) - b / a / 3;
                x3 = 2 * Math.Sqrt(-p / 3) * Math.Cos(f / 3 + 4 * Math.PI / 3) - b / a / 3;
            }

            if (s > 0) {
                double y1 = 0, y2 = 0;
                if (-q / 2 + Math.Sqrt(s) > 0) y1 = Math.Exp(Math.Log(Math.Abs(-q / 2 + Math.Sqrt(s))) / 3);
                if (-q / 2 + Math.Sqrt(s) < 0) y1 = -Math.Exp(Math.Log(Math.Abs(-q / 2 + Math.Sqrt(s))) / 3);
                if (-q / 2 + Math.Sqrt(s) == 0) y1 = 0;
                if (-q / 2 - Math.Sqrt(s) > 0) y2 = Math.Exp(Math.Log(Math.Abs(-q / 2 - Math.Sqrt(s))) / 3);
                if (-q / 2 - Math.Sqrt(s) < 0) y2 = -Math.Exp(Math.Log(Math.Abs(-q / 2 - Math.Sqrt(s))) / 3);
                if (-q / 2 - Math.Sqrt(s) == 0) y2 = 0;
                x1 = y1 + y2 - b / a / 3;
                x2 = Double.NaN;
                x3 = Double.NaN;
            }
            if (s == 0) {
                double y1 = 0;
                if (q < 0) y1 = Math.Pow(Math.Abs(-q / 2), 1.0 / 3);
                if (q > 0) y1 = -Math.Pow(Math.Abs(-q / 2), 1.0 / 3);
                if (q == 0) y1 = 0;
                x1 = 2 * y1 - b / a / 3;
                x2 = -y1 - b / a / 3;
                x3 = x2;
            }
        }
    }
}
